/*
 * Socket.h
 *
 *  Created on: 2011-6-24
 *      Author: wuwentai
 */

#include   <winsock2.h> 
//#pragma     comment(lib, "ws2_32.lib ")
#include <string>
#include <process.h>
#include <windows.h>

 
using namespace std;



#define ARRAY_SIZE(x) ((int)(sizeof(x)/sizeof(x[0])))
#define MAX_BUF_SIZE 2048




class Msg
{
public:
	Msg(int length,int tmplength,const char* content,SOCKET sock)
	{
		m_length = length;
		m_content = new char[length];
		if (tmplength != 0)
		{
			memcpy(m_content,content,tmplength);
		}		
		m_curpos = tmplength;
		m_socket = sock;
		m_next = NULL;
	
	}
	Msg(int length,const char* content,SOCKET sock)
	{
		m_length = length;
		m_content = new char[length];
		memcpy(m_content,content,length);
		m_curpos = length;
		m_socket = sock;
		m_next = NULL;
	};
	Msg(){m_curpos = 0;m_next = NULL;}
	~Msg()
	{
		if (m_content!=NULL)
		{
			delete m_content;
		}		
	};

	int	m_length;
	int m_curpos;
	char* m_content;
	SOCKET m_socket;
	Msg* m_next;
};


class MsgList 
{
public:
	MsgList()
	{
		m_first = NULL;
		m_ListMutex = CreateMutex(NULL,FALSE,NULL);
	};
	~MsgList()
	{
		Msg* tmp = m_first;
		while(tmp!=NULL)
		{
			m_first = m_first->m_next;
			delete tmp;
			tmp = m_first;
		}
		CloseHandle(m_ListMutex);
	};

	void AddMsgToList(Msg* msg)
	{	
		if(WAIT_OBJECT_0 == WaitForSingleObject(m_ListMutex, INFINITE))
		{
			if (m_first == NULL)
			{
				m_first = msg;
			}else
			{
				Msg* tmp = m_first;
				while(tmp->m_next != NULL)
					tmp = tmp->m_next;
				tmp->m_next = msg;
			}
			ReleaseMutex(m_ListMutex);
		}				
	};	
	Msg* GetMsgFromList()
	{	
		Msg* tmp;
		if(WAIT_OBJECT_0 == WaitForSingleObject(m_ListMutex, INFINITE))
		{
			if (m_first == NULL)
			{
				tmp = NULL;
			}else
			{
				tmp = m_first;
				m_first = m_first->m_next;
				tmp->m_next = NULL;
			}	
			ReleaseMutex(m_ListMutex);
		}
		return tmp;
	};

private:
	Msg*	m_first;
	HANDLE	m_ListMutex;
};


class Socket {
public:	
	Socket(SOCKET socket = INVALID_SOCKET);
	virtual ~Socket();

	SOCKET Detach();

	int Create(char* ip = NULL, int port = 0);
	void Close();

	int getSockName(std::string& ip, int& port);
	int getPeerName(std::string& ip, int& port);
	int getPeerName(struct sockaddr_in* peer);

	int Connect(const char* rip, int rport);
	int Send(Msg* msg);
	int Recv(void* buf, int len);

	SOCKET getFD() { return m_socket; }

	string PickUpMsg();


	MsgList* m_SockMsgRecvList;
	MsgList* m_SockMsgSendList;

private:
	SOCKET	m_socket;
	Msg*	m_RecvTmpMsg;
	Msg*	m_SendTmpMsg;
	char	m_TmpRecvLength[4];
	unsigned		m_TmpRecvLengthNum;
	char	m_TmpSendLength[4];
	unsigned		m_TmpSendLengthNum;
};